from django.http import HttpResponse, HttpResponseRedirect, Http404
from django.views.decorators.http import require_http_methods
from django.shortcuts import render_to_response, redirect
from django import forms
from django.template import RequestContext
from django.core.urlresolvers import reverse
from django.utils import simplejson

import tempfile
import hashlib
import zipfile
from models import App, AppStatus, get_apkid, lookup_apkid
from django.core.servers.basehttp import FileWrapper

import apkstorage
import os

class UploadFileForm(forms.Form):
    file  = forms.FileField()

## Handler for user sending app
@require_http_methods(["POST", "GET"])
def sendfile(request):
    form = UploadFileForm(request.POST, request.FILES)
    if form.is_valid():
        return handle_uploaded_file(request, request.FILES['file'])
    else:
        return load_page_template(request, "", "File upload failed.")
    
def add_apk_file(f, hash):
    try:
        apk_file = zipfile.ZipFile(f)
#        apk_file.read("AndroidManifest.xml")
    except zipfile.BadZipfile:
        return None
    
    if not "AndroidManifest.xml" in apk_file.namelist():
        return None
    
    apk = App(filename = f.name, filehash = hash, status = AppStatus.STATUS_Init)
    apk.save()
    
    apkstorage.storeUploadedAPK(f, apk)
    apk.status = AppStatus.STATUS_Uploaded
    apk.save()
    
    return apk

def handle_uploaded_file(request, f):
    tmpfile = tempfile.TemporaryFile()
    hash_ctx = hashlib.sha1()
    
    for chunk in f.chunks():
        hash_ctx.update(chunk)
    
    filehash = hash_ctx.hexdigest()

    apk_record = add_apk_file(f, filehash)
    if apk_record:
        apk_id = get_apkid(apk_record)
    else:
        apk_id = ""

    tmpfile.close()
    
    if apk_id:
        return render_to_response('apk/main.html', 
                              { 'page_name': "submit",
                                'apk_id' : apk_id,
                                'next_url' : reverse("webui.apk.views.downloadfile", args=(apk_id, )),
                               },
                              context_instance=RequestContext(request))
    else:
        return render_to_response('apk/main.html', 
                              { 'page_name': "submit",
                                'message' : "Invalid apk file.", 
                               },
                              context_instance=RequestContext(request))
    
# AJAX handler for returning apk information
def ajax_appinfo(request, apk_id):
    if request.is_ajax():
        apk = lookup_apkid(apk_id)
        if apk:
            apk_info = {}
            
            if apk.status == AppStatus.STATUS_Processed:
                apk_info['status'] = 'processed'
            elif apk.status == AppStatus.STATUS_Failed:
                apk_info['status'] = 'failed'
            else:
                apk_info['status'] = 'pending'
            
            apk_info['url'] = reverse("webui.apk.views.getfile", args=(apk_id, ))
            apk_info['filename'] = apk.filename
            data = simplejson.dumps(apk_info)
            return HttpResponse(data, "application/javascript; charset=utf8")
    raise Http404 

## Handler for user retrieving app
def downloadfile(request, apk_id):
    return render_to_response('apk/main.html', 
                          { 'page_name': "download",
                            'retrieve_apk_id' : apk_id, 
                           },
                          context_instance=RequestContext(request))
        
def getfile(request, apk_id):
    apk = lookup_apkid(apk_id)
    if not apk or apk.status != AppStatus.STATUS_Processed:
        raise Http404
    
    apk_path = apkstorage.getProcessedAPKPath(apk)
    if not os.path.exists(apk_path):
        #TODO: LOG error msg.
        raise Http404
    
    response = HttpResponse(open(apk_path, "rb"), mimetype = "application/octet-stream")
    response['Content-Disposition'] = 'attachment; filename=%s' % apk.filename
    response['Content-Length'] = os.path.getsize(apk_path)
    return response

## Loading html page
pagenames = set(["submit", "download", "faq", "about"])
@require_http_methods(["GET"])
def showpage(request, page_name):
    return load_page_template(request, page_name)

def load_page_template(request, page_name, initial_msg = ""):
    if not page_name in pagenames:
        page_name = "submit"
    return render_to_response('apk/main.html', 
                              { 'page_name': page_name,
                                'message' : initial_msg,
                               },
                              context_instance=RequestContext(request))
    